package com.jg.poiet.word;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.jg.poiet.exception.WordException;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.PicturesTable;
import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.hwpf.usermodel.Paragraph;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class HWPFNiceWord extends NiceWord {

    private static BaseFont PDF_FONT = null;

    static {
        try {
            PDF_FONT = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        } catch (Exception ignore) {
        }
    }

    private HWPFDocument document;
    PicturesTable picturesTable;

    public HWPFNiceWord(HWPFDocument document) {
        this.document = document;
        this.picturesTable = document.getPicturesTable();
    }

    @Override
    public void writeToPdfFile(String path) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            Document pdfDoc = new Document();
            PdfWriter writer = PdfWriter.getInstance(pdfDoc, fos);
            pdfDoc.open();

            Range range = document.getRange();

            Map<Integer, Integer> listIndexMap = new HashMap<>();
            Set<Paragraph> used = new HashSet<>();
            int end = 0;
            for (int i = 0; i < range.numParagraphs(); i++) {
                Paragraph paragraph = range.getParagraph(i);
                if (paragraph.getEndOffset() <= end) {
                    continue;
                }
                if (paragraph.isInTable()) {
                    end = range.getTable(paragraph).getEndOffset();
                } else {
                    end = paragraph.getEndOffset();
                }
                Element element = buildPdfElement(paragraph, range, listIndexMap, 1);
                if (element != null) {
                    pdfDoc.add(element);
                }
            }
            pdfDoc.close();
        } catch (Exception e) {
            throw new WordException("word转pdf失败！");
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception ignore) { }
        }
    }

    private Element buildPdfElement(Paragraph paragraph,Range range, Map<Integer, Integer> listIndexMap, int tableLevel)
            throws IOException, DocumentException {
        if (paragraph.isInList()) {
            Integer listIndex = listIndexMap.getOrDefault(paragraph.getIlfo(), 0);
            listIndexMap.put(paragraph.getIlfo(), listIndex + 1);
        }
        if (paragraph.isInTable()) {
            if (paragraph.getTableLevel() != tableLevel) {
                return null;
            }
            //表格
            try {
                Table tb = range.getTable(paragraph);
                PdfPTable pdfTable = null;
                for (int rowIndex = 0; rowIndex < tb.numRows(); rowIndex++) {
                    TableRow tr = tb.getRow(rowIndex);
                    if (pdfTable == null) {
                        pdfTable = new PdfPTable(tr.numCells());
                        pdfTable.setWidthPercentage(100);
                        //段前距离
                        pdfTable.setSpacingBefore((paragraph.getSpacingBefore()/ 20F) + 2 * 1.33F);
                        //段后距离
                        pdfTable.setSpacingAfter((paragraph.getSpacingAfter()/ 20F) + 2 * 1.33F);
                    }
                    for (int cellIndex = 0;cellIndex < tr.numCells(); cellIndex++) {
                        TableCell td = tr.getCell(cellIndex);
                        PdfPCell cell = new PdfPCell();
                        int end = 0;
                        for (int k = 0; k < td.numParagraphs(); k++) {
                            Paragraph para = td.getParagraph(k);
                            if (para.getEndOffset() <= end) {
                                continue;
                            }
                            if (para.getTableLevel() == tableLevel + 1) {
                                end = td.getTable(para).getEndOffset();
                            } else {
                                end = para.getEndOffset();
                            }
                            Element element = buildPdfElement(para, td, listIndexMap, tableLevel + 1);
                            if (element == null) {
                                element = buildPdfParagraph(para);
                            }
                            if (element != null) {
                                cell.addElement(element);
                            }
                        }
                        if (tr.getRowHeight() > 0) {
                            cell.setMinimumHeight(tr.getRowHeight()/1440f * 80);
                        }
                        pdfTable.addCell(cell);
                    }
                }
                return pdfTable;
            } catch (Exception ignore) {
                ignore.printStackTrace();
                return null;
            }
        } else if (paragraph.isInList()) {
            return buildPdfParagraph(paragraph, listIndexMap.get(paragraph.getIlfo()) + "、");
        } else {
            int styleIndex = paragraph.getStyleIndex();
            if (styleIndex == 19) {
                //目录处理
                return buildPdfParagraphWhenStyleIndex19(paragraph);
            }
            return buildPdfParagraph(paragraph);
        }
    }

    private com.itextpdf.text.Paragraph buildPdfParagraph(Paragraph paragraph) throws IOException, DocumentException {
        return buildPdfParagraph(paragraph, "");
    }

    private com.itextpdf.text.Paragraph buildPdfParagraph(Paragraph paragraph, String prevStr) throws IOException, DocumentException {
        String text = paragraph.text();
        ParagraphProperties properties = paragraph.getProps();
        com.itextpdf.text.Paragraph pdfParagraph = new com.itextpdf.text.Paragraph();
        float maxFontSize = 14;
        //对齐方式
        int justification = paragraph.getJustification();
        if (justification == 0) { //左对齐
            pdfParagraph.setAlignment(Element.ALIGN_LEFT);
        } else if (justification == 1) { //居中对齐
            pdfParagraph.setAlignment(Element.ALIGN_CENTER);
        } else if (justification == 2) { //右对齐
            pdfParagraph.setAlignment(Element.ALIGN_RIGHT);
        } else { //左右对齐
            pdfParagraph.setAlignment(Element.ALIGN_LEFT);
        }
        //缩进
        pdfParagraph.setFirstLineIndent(properties.getFirstLineIndent() / 20 * 1.33F);
        //段前距离
        pdfParagraph.setSpacingBefore((paragraph.getSpacingBefore()/ 20F) + 2 * 1.33F);
        //段后距离
        pdfParagraph.setSpacingAfter((paragraph.getSpacingAfter()/ 20F) + 2 * 1.33F);
        //行距
        pdfParagraph.setMultipliedLeading((paragraph.getLineSpacing().toInt() - 65536) / 240F);
        //遍历添加文字
        for (int i = 0; i < paragraph.numCharacterRuns(); i++) {
            CharacterRun characterRun = paragraph.getCharacterRun(i);
            Font font = new Font(PDF_FONT);
            if (picturesTable.hasPicture(characterRun)) {
                if (i == 0 && prevStr != null) {
                    pdfParagraph.add(new Chunk(prevStr, font));
                }
                Picture picture = picturesTable.extractPicture(characterRun, false);
                Image img = Image.getInstance(picture.getContent());
                img.scaleAbsolute(img.getWidth() * (picture.getHorizontalScalingFactor() / 1000F),
                        img.getHeight() * (picture.getVerticalScalingFactor() / 1000F));
                Chunk chunk = new Chunk(img, 0, 0, true);
                pdfParagraph.add(chunk);
            } else {
                //字体颜色
                if (characterRun.getIco24() > 0) {
                    font.setColor(
                            (characterRun.getIco24()) & 0xff,
                            (characterRun.getIco24() >> 8) & 0xff,
                            (characterRun.getIco24() >> 16) & 0xff
                    );
                }
                //字体大小
                font.setSize(characterRun.getFontSizeAsDouble().floatValue() / 2);
                if (characterRun.getFontSizeAsDouble().floatValue() / 2 > maxFontSize) {
                    maxFontSize = characterRun.getFontSizeAsDouble().floatValue() / 2;
                }
                String style = "";
                //是否加粗
                if (characterRun.isBold()) {
                    style += Font.FontStyle.BOLD.getValue();
                }
                //是否斜字体
                if (characterRun.isItalic()) {
                    style += Font.FontStyle.ITALIC.getValue();
                }
                font.setStyle(style);
                if (i == 0 && prevStr != null) {
                    pdfParagraph.add(new Chunk(prevStr, font));
                }
                Chunk t = new Chunk(characterRun.text(), font);
                pdfParagraph.add(t);
            }
        }
        pdfParagraph.setFont(new Font(PDF_FONT, maxFontSize));
        return pdfParagraph;
    }

    private com.itextpdf.text.Paragraph buildPdfParagraphWhenStyleIndex19(Paragraph paragraph) throws IOException, DocumentException {
        String text = paragraph.text();
        ParagraphProperties properties = paragraph.getProps();
        com.itextpdf.text.Paragraph pdfParagraph = new com.itextpdf.text.Paragraph();
        float maxFontSize = 14;
        //对齐方式
        int justification = paragraph.getJustification();
        if (justification == 0) { //左对齐
            pdfParagraph.setAlignment(Element.ALIGN_LEFT);
        } else if (justification == 1) { //居中对齐
            pdfParagraph.setAlignment(Element.ALIGN_CENTER);
        } else if (justification == 2) { //右对齐
            pdfParagraph.setAlignment(Element.ALIGN_RIGHT);
        } else { //左右对齐
            pdfParagraph.setAlignment(Element.ALIGN_LEFT);
        }
        //缩进
        pdfParagraph.setFirstLineIndent(properties.getFirstLineIndent() / 20 * 1.33F);
        //段前距离
        pdfParagraph.setSpacingBefore((paragraph.getSpacingBefore()/ 20F) + 2 * 1.33F);
        //段后距离
        pdfParagraph.setSpacingAfter((paragraph.getSpacingAfter()/ 20F) + 2 * 1.33F);
        //行距
        pdfParagraph.setMultipliedLeading((paragraph.getLineSpacing().toInt() - 65536) / 240F);
        //遍历添加文字
        List<Chunk> chunks = new ArrayList<>();
        chunks.add(new Chunk("         "));
        for (int i = 0; i < paragraph.numCharacterRuns(); i++) {
            CharacterRun characterRun = paragraph.getCharacterRun(i);
            String textStr = characterRun.text();
            if (textStr == null || textStr.trim().length() == 0) {
                continue;
            }
            String textStrLow = textStr.toLowerCase();
            if (textStrLow.contains("toc")
                    || textStrLow.contains("hyperlink")
                    || textStrLow.contains("pagerer")) {
                continue;
            }
            Font font = new Font(PDF_FONT);
            //字体颜色
            if (characterRun.getIco24() > 0) {
                font.setColor(
                        (characterRun.getIco24()) & 0xff,
                        (characterRun.getIco24() >> 8) & 0xff,
                        (characterRun.getIco24() >> 16) & 0xff
                );
            }
            //字体大小
            font.setSize(characterRun.getFontSizeAsDouble().floatValue() / 2);
            if (characterRun.getFontSizeAsDouble().floatValue() / 2 > maxFontSize) {
                maxFontSize = characterRun.getFontSizeAsDouble().floatValue() / 2;
            }
            String style = "";
            //是否加粗
            if (characterRun.isBold()) {
                style += Font.FontStyle.BOLD.getValue();
            }
            //是否斜字体
            if (characterRun.isItalic()) {
                style += Font.FontStyle.ITALIC.getValue();
            }
            font.setStyle(style);
            Chunk t = new Chunk(characterRun.text(), font);
            chunks.add(t);
        }
        float textWidth = 0;
        Chunk lastChunk = null;
        for (int i = 0; i < chunks.size(); i++) {
            Chunk t = chunks.get(i);
            if (i < chunks.size() - 1) {
                pdfParagraph.add(t);
                textWidth += t.getWidthPoint();
            } else {
                lastChunk = t;
                textWidth += lastChunk.getWidthPoint();
            }
        }
        int pointNum = (int)((480 - textWidth) / 3.336);
        StringBuilder tValue = new StringBuilder();
        for (int i = 0; i < pointNum; i++) {
            tValue.append(".");
        }
        pdfParagraph.add(new Chunk(tValue.toString()));
        pdfParagraph.add(lastChunk);
        pdfParagraph.setFont(new Font(PDF_FONT, maxFontSize));
        return pdfParagraph;
    }

}
